import os
import enum
from src.sup_function import normalize_text
import json


class CmakeResults(enum.Enum):
    file_not_found = 'Cannot find source file'
    no_sources = 'No SOURCES given to target'
    linker_language = 'CMake can not determine linker language for target'


def get_cmake_errors(file_path: str):
    """
    Функция, проверяющая один cmake файл: при ошибке выводит информацию о ней, иначе возвращает True
    :param file_path: путь до файла cmake
    :return:
    """
    with open(file_path, 'r') as file:
        string_list = [i_string for i_string in file if i_string != '\n']
        for number, i_string in enumerate(string_list):
            if 'CMake Error' in i_string:
                if 'Warning' in string_list[number + 1]:
                    error = ' '.join(string_list[number: number + 1]).replace('\n ', '')
                elif 'failed' in string_list[number + 2]:
                    error = ' '.join(string_list[number: number + 2]).replace('\n ', '')
                else:
                    error = ' '.join(string_list[number: number + 3]).replace('\n ', '')
                for i in CmakeResults:
                    if i.value in string_list[number + 1] \
                            or i.value in string_list[number + 2] \
                            or i.value in string_list[number]:
                        yield i.name, error  # генератор, возвращает ошибку и ее значение


def create_cmake_report(directory: str, reports_list: list, reports: dict) -> dict:
    """
    Функция, создающая список найденных ошибок во всех файлах cmake
    :param directory:
    :param reports:
    :param reports_list:
    :return: словарь ошибок
    """
    if not reports_list:
        if 'success' not in reports:
            reports['success'] = {}
        reports['success'][directory] = 'Build files have been written'
        return reports
    if 'errors' not in reports:
        reports['errors'] = {}
    reports['errors'][directory] = {}
    for res in reports_list:
        reports['errors'][directory][res[0]] = res[1]
    reports['errors'][directory]['count_errors'] = len(reports_list)
    return reports


def collect_cmake_data(path_dir, reports=None):
    """
    Функция, проверяющая директории и находящая файлы cmake, а также считающая количество ошибок в cmake
    :param reports:
    :param path_dir: путь до необходимой директории
    :return: словарь ошибок
    """
    if reports is None:
        reports = {}
    for i_file in os.listdir(path_dir):
        if os.path.isfile(os.path.join(path_dir, i_file)) and 'cmake' in i_file:
            print(path_dir.split('\\')[::-1][1])  # вывод названия директории
            results = [res for res in get_cmake_errors(os.path.join(path_dir, i_file))]
            if results:
                for res in results:
                    print(normalize_text(': '.join(res)))
            else:
                print('Build files have been written')
            create_cmake_report(path_dir.split('\\')[::-1][1], results, reports)
            print('=' * 80)
        elif os.path.isdir(os.path.join(path_dir, i_file)):
            collect_cmake_data(os.path.join(path_dir, i_file), reports=reports)
    return reports


def print_errors(reports: dict) -> None:
    """
    Функция, выводящаяя словарь ошибок в нормализованном виде
    :param reports:
    :return:
    """

    with open("data.json", "w") as file:
        json.dump(reports, file, indent=4)

    # for key, value in reports.items():
    #     print(f'{key}:')
    #     for i_error in value:
    #         print(normalize_text(f'{i_error}'))


if __name__ == '__main__':
    folder_path = r'C:\Users\anyca\Desktop\TestResults_Unpack'
    print_errors(collect_cmake_data(folder_path))
